package com.jzo2o.orders.manager.handler;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.jzo2o.api.trade.RefundRecordApi;
import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO;
import com.jzo2o.api.trade.enums.RefundStatusEnum;
import com.jzo2o.common.constants.UserType;
import com.jzo2o.common.utils.BeanUtils;
import com.jzo2o.common.utils.CollUtils;
import com.jzo2o.orders.base.enums.OrderRefundStatusEnum;
import com.jzo2o.orders.base.model.domain.Orders;
import com.jzo2o.orders.base.model.domain.OrdersRefund;
import com.jzo2o.orders.manager.model.dto.OrderCancelDTO;
import com.jzo2o.orders.manager.service.IOrdersCreateService;
import com.jzo2o.orders.manager.service.IOrdersManagerService;
import com.jzo2o.orders.manager.service.IOrdersRefundService;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;

@Component
@Slf4j
public class OrderHandler {
    @Resource
    private IOrdersCreateService ordersCreateService;
    @Resource
    private IOrdersManagerService ordersManagerService;
    @Resource
    private IOrdersRefundService ordersRefundService;
    @Resource
    private RefundRecordApi refundRecordApi;
    @Resource
    private OrderHandler orderHandler;

    /**
     * 支付超时取消订单 实现方式1
     */
    @XxlJob(value = "cancelOverTimePayOrder")
    public void cancelOverTimePayOrder() {
        // 支付超时的订单
        List<Orders> orderList = ordersCreateService.queryOverTimePayOrdersListByCount(100);
        if(CollectionUtils.isEmpty(orderList)) {
            return;
        }

        orderList.forEach(item -> {
            OrderCancelDTO orderCancelDTO = BeanUtils.toBean(item, OrderCancelDTO.class);
            orderCancelDTO.setCurrentUserType(UserType.SYSTEM);
            orderCancelDTO.setCancelReason("支付超时，自动取消支付");
            ordersManagerService.cancel(orderCancelDTO);
        });
    }

    /**
     * 取消已支付(分配中)的订单
     */
    @XxlJob("handleRefundOrders")
    public void handleRefundOrders() {
        // 查询带退款信息
        List<OrdersRefund> ordersRefundList = ordersRefundService.queryRefundOrderListByCount(100);
        if(CollUtils.isEmpty(ordersRefundList)) {
            return ;
        }
        // 遍历退款信息集合请求微信退款接口，执行退款
        requestRefundOrder(ordersRefundList);

        // 更新订单退款信息
    }

    /**
     * 请求微信退款接口，执行退款
     * @param ordersRefundList
     */
    private void requestRefundOrder(List<OrdersRefund> ordersRefundList) {
        ordersRefundList.forEach(item -> {
            ExecutionResultResDTO wxRemoteResult = null;
            try {
                wxRemoteResult = refundRecordApi.refundTrading(item.getTradingOrderNo(), item.getRealPayAmount());
            } catch (Exception e) {
                e.printStackTrace();
            }

            // 修改订单的退款状态
            if(wxRemoteResult != null) {
                orderHandler.updateRefundOrder(item, wxRemoteResult);
            }
        });
    }

    /**
     * 修改订单状态
     * @param item
     * @param wxRemoteResult
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateRefundOrder(OrdersRefund item, ExecutionResultResDTO wxRemoteResult) {
        int refundStatus = OrderRefundStatusEnum.REFUNDING.getStatus();

        if (ObjectUtil.equal(RefundStatusEnum.SUCCESS.getCode(), wxRemoteResult.getRefundStatus())) {
            //退款成功
            refundStatus = OrderRefundStatusEnum.REFUND_SUCCESS.getStatus();
        } else if (ObjectUtil.equal(RefundStatusEnum.FAIL.getCode(), wxRemoteResult.getRefundStatus())) {
            //退款失败
            refundStatus = OrderRefundStatusEnum.REFUND_FAIL.getStatus();
        }

        LambdaUpdateWrapper<Orders> wrapper = new LambdaUpdateWrapper<Orders>()
                .eq(Orders::getId, item.getId())
                .ne(Orders::getRefundStatus, refundStatus)
                .set(Orders::getRefundStatus, refundStatus)
                .set(ObjectUtil.isNotEmpty(wxRemoteResult.getRefundId()), Orders::getRefundId, wxRemoteResult.getRefundId())
                .set(ObjectUtil.isNotEmpty(wxRemoteResult.getRefundNo()), Orders::getRefundNo, wxRemoteResult.getRefundNo());

        boolean update = ordersManagerService.update(wrapper);

        if(update) {
            ordersRefundService.removeById(item.getId());
        }
    }
}
